package org.surelink.radius.middleware.auth;

import org.surelink.radius.cache.GroupCache;
import org.surelink.radius.cache.UserCache;
import org.surelink.radius.constant.Constant;
import org.surelink.radius.constant.FeePolicys;
import org.surelink.radius.middleware.AuthMiddleware;
import org.surelink.radius.model.User;
import org.surelink.radius.utils.DateTimeUtil;
import org.surelink.radius.utils.ValidateUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.tinyradius.attribute.IntegerAttribute;
import org.tinyradius.packet.AccessRequest;
import org.tinyradius.packet.RadiusPacket;

public class AuthSessionMiddleware implements AuthMiddleware
{

    private static final Logger log = Logger.getLogger(AuthSessionMiddleware.class);

    @Autowired
    private UserCache userCache;

    @Autowired
    private GroupCache groupCache;

    @Override
    public RadiusPacket onAuth(User user, AccessRequest request, RadiusPacket response) throws Exception {

        if(log.isInfoEnabled())
            log.info("start AuthSessionMiddleware ...");
        // 获取最大会话时长
        int sessionTimeout = 86400;
        String stimeoutattr = groupCache.getGroupMeta(user.getGroupName(), Constant.GROUP_DEFAULT_SESSIONTIME.value());
        if (stimeoutattr != null)
            sessionTimeout = Integer.valueOf(stimeoutattr);


        //判断到期

        String attr = userCache.getUserMeta(user.getUserName(), Constant.USER_EXPIRE.value());

        if (attr != null) {
            // 用户当晚到期
            if (attr.equals(DateTimeUtil.getDateString())) {
                String dateTime = DateTimeUtil.getDateTimeString();
                int _timeout = DateTimeUtil.compareSecond(attr + " 23:59:59", dateTime);
                if (_timeout < sessionTimeout)
                    sessionTimeout = _timeout;
            } else if (DateTimeUtil.compareDay(attr, DateTimeUtil.getDateString()) < 0) {
                response.setPacketType(RadiusPacket.ACCESS_REJECT);
                response.addAttribute("Reply-Message", "用户已经到期");
                return response;
            }
        }

        //上网时段校验
        String periodAttr = userCache.getUserMeta(user.getUserName(), Constant.USER_PERIOD.value());
        int periodTimelen = checkPeriod(periodAttr, sessionTimeout);
        if (periodTimelen == 0) {
            response.setPacketType(RadiusPacket.ACCESS_REJECT);
            response.addAttribute("Reply-Message", "时段限制");
            return response;
        }
        else
            sessionTimeout = periodTimelen;

        // 根据余额反算时长
        String policy = groupCache.getGroupMeta(user.getGroupName(), Constant.GROUP_FEE_POLICY.value());
        String price = groupCache.getGroupMeta(user.getGroupName(), Constant.GROUP_FEE_PRICE.value());
        String userCredit = userCache.getUserMeta(user.getUserName(), Constant.USER_CREDIT.value());
        int timelen = calcTimelen(policy,price,userCredit, sessionTimeout);
        if (timelen == 0) {
            response.setPacketType(RadiusPacket.ACCESS_REJECT);
            response.addAttribute("Reply-Message", "用户余额不足");
            return response;
        } else
            sessionTimeout = timelen;


        response.addAttribute(new IntegerAttribute(27, sessionTimeout));
        return response;
    }


    /**
     * 上网时段校验
     *
     * @param periodAttr
     * @param sessionTimeout
     * @return
     */
    private int checkPeriod(String periodAttr, int sessionTimeout) {

        if (periodAttr != null && !ValidateUtil.isEmpty(periodAttr)) {
            String startTime = periodAttr.substring(0, 5);
            String endTime = periodAttr.substring(6, 11);
            String nowDay = DateTimeUtil.getDateString();
            String afterDay = DateTimeUtil.getNextDateStringAddDay(nowDay, 1);
            String nowTime = DateTimeUtil.getDateTimeString();
            String nowHour = DateTimeUtil.getTimeString().substring(0, 5);

            // 时段判断
            boolean _auth = true;
            if (startTime.compareTo(endTime) < 0
                    && (nowHour.compareTo(startTime) < 0 || nowHour.compareTo(endTime) > 0))
                _auth = false;
            else if (startTime.compareTo(endTime) > 0
                    && (nowHour.compareTo(startTime) < 0 && nowHour.compareTo(endTime) > 0))
                _auth = false;

            if (!_auth)
                return 0;

            // 会话超时时长计算
            if (startTime.compareTo(endTime) < 0)
                endTime = nowDay + " " + endTime + ":00";
            else if (nowTime.compareTo(nowDay + " " + startTime + ":00") > 0)
                endTime = afterDay + " " + endTime + ":00";// 跨天
            else
                endTime = nowDay + " " + endTime + ":00";

            int timeLenth = DateTimeUtil.compareSecond(endTime, nowTime);
            if (timeLenth < sessionTimeout)
                sessionTimeout = timeLenth;
        }
        return sessionTimeout;
    }

    /**
     * 根据余额反算时长
     * @param policy
     * @param price
     * @param userCredit
     * @param sessionTimeout
     * @return
     */
    private int calcTimelen(String policy,String price,String userCredit, int sessionTimeout) {

        int _price = price != null ? Integer.valueOf(price) : 0;
        if (policy != null) {
            int _policy = Integer.valueOf(policy);
            if (_policy == FeePolicys.PrePay_TimeLen.value()) {
                if (userCredit == null)
                    return 0;

                int credit = Integer.valueOf(userCredit);
                int timeLenth = (int) ((credit) * 60 * 60 / _price);
                if (timeLenth < sessionTimeout)
                    sessionTimeout = timeLenth;
            }
        }
        return sessionTimeout;
    }
}
